import tkinter as tk
from tkinter import filedialog as fd
from tkinter import font
from tkinter import Tk, Frame, ttk
import subprocess
import argparse  # 传参数用
import configparser  # 读取excel位置用
import os  # 检测文件
import logging  # 输出日志
from openpyxl import load_workbook  # 导入 openpyxl 库中的读取 Excel 的函数
import datetime

print("可以使用 -f 参数来加载文件！")

# 配置定义：debug
debug = True

# 获取Logger对象
logger = logging.getLogger("ExcelViewer")
formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
console_handler = logging.StreamHandler()
console_handler.setFormatter(formatter)

# 设置Logger对象的level属性
if debug == True:
    logger.setLevel(logging.DEBUG)
    console_handler.setLevel(logging.DEBUG)
else:
    logger.setLevel(logging.WARNING)
    console_handler.setLevel(logging.WARNING)

logger.addHandler(console_handler)


## 包安装定义
def install_package(package_name):
    try:
        subprocess.check_call(["pip", "install", package_name])
    except subprocess.CalledProcessError:
        print(f"无法安装包： {package_name}. 请检查网络后重试.")


# 查缺补漏 pandas
try:
    import pandas as pd
except ImportError:
    install_package("pandas")  # 如果导入失败，则尝试安装pandas


## 加载配置文件
config_File = "excel-config.ini"
config = configparser.ConfigParser()
if not os.path.exists(config_File):
    config["General"] = {"enableWindowDrag": "yes"}

    with open(config_File, "w") as f:
        config.write(f)

config.read(config_File)

## 添加参数用于指定命令加载excel
parser = argparse.ArgumentParser(description="指定读取的excel文件")
parser.add_argument("-f", default=None, help="如无指定，将打开窗口选择文件")





class ExcelViewer(tk.Tk):  # 基于 Tkinter.Tk 类定义一个名为 ExcelViewer 的新类
 
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)  # 对基类初始化方法进行调用
        self.title("Excel Viewer")  # 设置窗口标题
        self.config(bg="white")  # 设置窗口背景颜色
        self.attributes("-alpha", 1)  # 隐藏边框（把opacity属性设为0.95）

        self.rowconfigure(0, weight=1)  # 使用 rowconfigure() 方法布局表格，使其能够自适应窗口大小
        self.columnconfigure(0, weight=1)
        ##GPT Start
        self.fontSize = font.Font(size=20)
        #GPT End


        ##GPT Start
        style = ttk.Style(self)
        style.configure('My.TFrame', font=('微软雅黑', 20))
        ##GPT End

        self.view_frame = tk.Frame(self, bg="white")  # 创建一个 Frame，显示表格数据

        ## GPT Start
        my_label = tk.Label(self.view_frame, bg='white', font=self.fontSize, text='My Label Text')
        my_label.pack()
        ## GPT End

        self.view_frame.grid(row=0, column=0, sticky="nsew")  #

        self.bind("<Map>", self._on_map)  # 绑定 Map 和 Configure 事件，实现窗口拖动改变大小时的事件响应
        self.drag_enabled = True
        self.bind("<B1-Motion>", self._on_drag)

        # 将右键菜单绑定到鼠标右键事件
        self.bind("<Button-3>", self._on_right_click)

        self._load_excel()  # 调用 _load_excel() 方法，开始读取 Excel 文件并展示数据

    def _load_excel(self):
        args = parser.parse_args()
        self.file_path = args.f
        if self.file_path == None:
            print("未指定文件")

            # 弹出文件选择窗口
            fileSelect = tk.Tk()
            fileSelect.withdraw()
            self.file_path = fd.askopenfilename(filetypes=[("Excel 文件", "*.xlsx")])
            if not self.file_path:
                raise ValueError("没有选择任何文件")

        # todo 可设定初始窗口坐标 [x]

        try:  # 检测加载的文件是否存在配置
            self.window_x = config.get(self.file_path, "window_x")
            self.window_y = config.get(self.file_path, "window_y")
            logger.info("正在尝试加载配置")
        
        except:
            self.window_x = "100"  # 默认窗口位置
            self.window_y = "200"
            config.add_section(self.file_path)
            config.set(self.file_path, "window_x", self.window_x)
            config.set(self.file_path, "window_y", self.window_y)
            with open(config_File, "w") as f:
                config.write(f)
            logger.warn("未检测到，正在新建专用配置")
        print(
            "[info] 本excel文件的窗口坐标是：" + self.window_x,
            self.window_y + ",按下右键以便记录当前坐标或取消移动",
        )

        workbook = load_workbook(
            filename=self.file_path, read_only=True
        )  # 打开 Excel 文件, read_only=True 表示只读取文件内容
        worksheet = workbook.active  # 获取 Excel 文件中的默认工作表对象
        rows = list(worksheet.rows)  # 将工作表对象转换成一行一行的列表
        ncols = len(rows[0])  # 计算工作表的列数
        logger.debug("表格列数:" + str(ncols))
        nrows = len(rows)  # 计算工作表的行数
        logger.debug("表格行数:" + str(nrows))

        for r, row in enumerate(rows):  # 遍历 rows 列表，并在 view_frame Frame 中显示
            for c, cell in enumerate(row):
                label = tk.Label(self.view_frame, text=cell.value)
                # 创建并放置 Label 控件，text 属性设为该单元格的值
                label.grid(row=r, column=c, sticky="nsew")

        self.geometry("{}x{}".format(ncols * 80, nrows * 25))  # 根据表格尺寸调整窗口大小

    def _on_map(self, event=None):
        self.update_idletasks()  # 更新窗口设置
        self.overrideredirect(True)  # 隐藏边框
        logger.debug("窗口大小"+str(self.winfo_reqwidth())+","+str(self.winfo_reqheight()))
        logger.debug("窗口坐标："+str(self.window_x)+","+str(self.window_y))

        self.geometry(
            "{}x{}+{}+{}".format(
                self.winfo_reqwidth(),
                self.winfo_reqheight(),
                self.window_x,
                self.window_y,
            )
        )

    def _on_drag(self, event):  # 让窗口响应拖动事件 ##搞了半小时 终于拖动正常了
        geo_str = f"+%s+%s" % (self.winfo_x() + event.x, self.winfo_y() + event.y)
        self.geometry(geo_str)

    def _on_option1_click(self):
            x = self.winfo_x()  # 窗口左上角的x坐标
            y = self.winfo_y()  # 窗口左上角的y坐标
            try:
                config.set(self.file_path, "window_x", str(x))  # 将当前窗口坐标写入配置文件中
                config.set(self.file_path, "window_y", str(y))
                with open(config_File, "w") as f:
                    config.write(f)
                print(f"已将窗口位置 ({x}, {y}) 写入配置文件,将在下次加载相同文件时应用")
            except:
                print("窗口没有对应的配置文件，需要先加载Excel文件并保存一次")


    def _on_option2_click(self):
        if self.drag_enabled:
            self.unbind("<B1-Motion>")  # 解绑窗口拖动事件
            self.drag_enabled = False
        else:
            self.bind("<B1-Motion>", self._on_drag)  # 重新绑定窗口拖动事件
            self.drag_enabled = True

    def _on_right_click(self, event):
        menu = tk.Menu(self, tearoff=False)
        menu.add_command(label="保存当前窗口位置", command=self._on_option1_click)
        menu.add_command(label="固定/反固定窗口", command=self._on_option2_click)
        menu.post(event.x_root, event.y_root)


if __name__ == "__main__":
    app = ExcelViewer()  # 创建该应用程序的实例
    app.mainloop()  #
